package product.service.rpc;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 发布服务
 * Created by ydw on 2017/6/27.
 */
public class RpcExporter {
    //Runtime.getRuntime().availableProcessors() 获取cpu的核心数
    //FixedThreadPool  这个是一个固定大小的线程池
    static Executor executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//根据电脑的核数创建线程池,最大化提高线程池的资源实用率

    public static void exporter(String hostName,int port)throws  Exception{

        ServerSocket server = new ServerSocket();
        server.bind(new InetSocketAddress(hostName,port));
        try {
            while (true){//监听TCP连接,
                executor.execute(new ExeporterTask(server.accept()));
            }
        }
        finally {
            server.close();
        }
    }
    //私有的内部类
    private static class ExeporterTask implements Runnable{
        Socket client=null;

        public ExeporterTask(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {
            ObjectInputStream input=null;
            ObjectOutputStream output=null;
            try {
                input= new ObjectInputStream(client.getInputStream());
                String interfaceName = input.readUTF();//获取接口的名字
                Class<?> service = Class.forName(interfaceName);//获取接口class文件
                String methodName = input.readUTF();//获取方法名字
                Class<?>[] parameterTypes = (Class<?>[]) input.readObject();//获取方法参数类型
                Object[] arguments = (Object[]) input.readObject();//获取方法参数
                Method method = service.getMethod(methodName, parameterTypes);//获取方法
                Object result = method.invoke(service.newInstance(), arguments);//通过反射传入参数和对象,运行方法获取方法的返回值
                output=new ObjectOutputStream(client.getOutputStream());
                output.writeObject(result);//通过socker把方法的返回值写出去
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                //关流,释放资源
                if (output!=null) {
                    try {
                        output.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (input!=null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (client!=null) {
                    try {
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
